﻿//------------------------------------------------------------------------------
//  Namespace: FruitVentDesign.UtilWindows
//  
//  Function： N/A
//  Name： PrintImageWindow
//  
//  Ver       Time                     Author
//  0.10      2021/6/17 15:19:10     FruitVent
//
//  此代码版权归作者本人FruitVent所有
//  源代码使用协议遵循本仓库的开源协议及附加协议，若本仓库没有设置，则按MIT开源协议授权
//  CSDN博客：https://blog.csdn.net/weixin_39552347
//  源代码仓库：https://gitee.com/fruitvent
//  感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using FruitVentDesign.Commands;
using FruitVentDesign.Enums;
using FruitVentDesign.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace FruitVentDesign.UtilWindows
{
    /// <summary>
    /// PrintImageWindow.xaml 的交互逻辑
    /// </summary>
    public partial class PrintImageWindow : Windows.Window
    {
        private string Watermark = null;

        /// <summary>
        /// 显示的图像源
        /// </summary>
        private ImageSource _imageSource;
        public ImageSource ImageSource
        {
            get => _imageSource;
            set
            {
                if (_imageSource != value)
                {
                    _imageSource = value;
                    OnPropertyChanged(nameof(ImageSource));
                }
            }
        }

        /// <summary>
        /// 打印机
        /// </summary>
        private string _printer = PrinterHelper.GetLocalPrinters()[0];
        public string Printer
        {
            get => _printer;
            set
            {
                if (_printer != value)
                {
                    _printer = value;
                    OnPropertyChanged(nameof(Printer));

                    //设置默认打印机
                    _ = PrinterHelper.SetDefaultPrinter(_printer);

                    PaperSizes = PrinterHelper.GetPaperSizes();
                    foreach (PaperSize item in PaperSizes)
                    {
                        if (item.Kind == PaperKind.A4) { PaperSize = item; }
                    }
                    paperSizeComboBox.SelectedValue = PaperKind.A4;
                }
            }
        }

        /// <summary>
        /// 打印机列表
        /// </summary>
        private List<string> _printers;
        public List<string> Printers
        {
            get
            {
                _printers = PrinterHelper.GetLocalPrinters();
                return _printers;
            }
            set
            {
                if (_printers != value)
                {
                    _printers = value;
                    OnPropertyChanged(nameof(Printers));
                }
            }
        }

        /// <summary>
        /// 纸张方向
        /// </summary>
        private bool _landscape = false;
        public bool Landscape
        {
            get => _landscape;
            set
            {
                if (_landscape != value)
                {
                    _landscape = value;
                    JudgmentExecution(PaperSize, _landscape);
                    OnPropertyChanged(nameof(Landscape));
                }
            }
        }

        /// <summary>
        /// 纸张方向列表
        /// </summary>
        private Dictionary<bool, string> _landscapes;
        public Dictionary<bool, string> Landscapes
        {
            get
            {
                _landscapes = PrinterHelper.GetLandscapes();
                return _landscapes;
            }
            set
            {
                if (_landscapes != value)
                {
                    _landscapes = value;
                    OnPropertyChanged(nameof(Landscapes));
                }
            }
        }

        /// <summary>
        /// 纸张大小
        /// </summary>
        private PaperSize _paperSize;
        public PaperSize PaperSize
        {
            get => _paperSize;
            set
            {
                if (_paperSize != value)
                {
                    _paperSize = value;
                    JudgmentExecution(_paperSize, Landscape);
                    OnPropertyChanged(nameof(PaperSize));
                }
            }
        }

        /// <summary>
        /// 纸张大小列表
        /// </summary>
        private System.Drawing.Printing.PrinterSettings.PaperSizeCollection _paperSizes;
        public System.Drawing.Printing.PrinterSettings.PaperSizeCollection PaperSizes
        {
            get
            {
                _paperSizes = PrinterHelper.GetPaperSizes();
                return _paperSizes;
            }
            set
            {
                if (_paperSizes != value)
                {
                    _paperSizes = value;
                    OnPropertyChanged(nameof(PaperSizes));
                }
            }
        }

        /// <summary>
        /// 当前页
        /// </summary>
        private int _current = 1;
        public int Current
        {
            get => _current;
            set
            {
                if (_current != value)
                {
                    _current = value;
                    OnPropertyChanged(nameof(Current));
                    ImageSource = GetImage(ImageFilePaths[_current - 1]);
                }
            }
        }

        /// <summary>
        /// 总页数
        /// </summary>
        private int _total = 1;
        public int Total
        {
            get => _total;
            set
            {
                if (_total != value)
                {
                    _total = value;
                    OnPropertyChanged(nameof(Total));
                }
            }
        }

        private List<string> ImageFilePaths { get; set; }

        /// <summary>
        /// 上一页
        /// </summary>
        private ICommand _previousCommad;
        public ICommand PreviousCommand
        {
            get
            {
                if (_previousCommad == null)
                {
                    _previousCommad = new SimpleCommand(OnPrevious, CanPrevious);
                }
                return _previousCommad;
            }
        }

        private bool CanPrevious()
        {
            return Current > 1;
        }

        private void OnPrevious()
        {
            if (Current > 1)
            {
                Current -= 1;
            }
        }

        /// <summary>
        /// 下一页
        /// </summary>
        private ICommand _nextCommad;
        public ICommand NextCommand
        {
            get
            {
                if (_nextCommad == null)
                {
                    _nextCommad = new SimpleCommand(OnNext, CanNext);
                }
                return _nextCommad;
            }
        }

        private bool CanNext()
        {
            return Current < Total;
        }

        private void OnNext()
        {
            if (Current < Total)
            {
                Current += 1;
            }
        }

        /// <summary>
        /// pages type
        /// </summary>
        private PagesType _pagesType = PagesType.All;
        public PagesType PagesType
        {
            get => _pagesType;
            set
            {
                if (_pagesType != value)
                {
                    _pagesType = value;
                    OnPropertyChanged(nameof(PagesType));
                }
            }
        }

        /// <summary>
        /// 切换页数选项
        /// </summary>
        private ICommand _switchPagesCommand;
        public ICommand SwitchPagesCommand
        {
            get
            {
                if(_switchPagesCommand == null)
                {
                    _switchPagesCommand = new SimpleCommand<string>(OnSwitchPages, CanSwitchPages);
                }
                return _switchPagesCommand;
            }
        }

        private bool CanSwitchPages(string arg)
        {
            if ((PagesType)System.Convert.ToInt32(arg) == PagesType.PageRangeMultiFrame && (ImageFilePaths is null || (ImageFilePaths != null && ImageFilePaths.Count == 0)))
            {
                return false; 
            }
            if ((PagesType)System.Convert.ToInt32(arg) == PagesType.PageRange && (ImageFilePaths is null || (ImageFilePaths != null && ImageFilePaths.Count == 0)))
            {
                return false;
            }

            return true;
        }

        private void OnSwitchPages(string obj)
        {
            PagesType = (PagesType)System.Convert.ToInt32(obj);
        }

        /// <summary>
        /// 显示纸张的缩放比例
        /// </summary>
        double scalingRatio = 1;

        /// <summary>
        /// 重新渲染画布
        /// </summary>
        /// <param name="heightPx"></param>
        /// <param name="widthPx"></param>
        private void Reset(double heightPx, double widthPx)
        {
            scalingRatio = 1;
            if (Box.ActualHeight > 0 && Box.ActualWidth > 0)
            {
                while (heightPx > (Box.ActualHeight - 8) || widthPx > (Box.ActualWidth - 8))
                {
                    scalingRatio -= 0.00000001;
                    heightPx = heightPx * scalingRatio;
                    widthPx = widthPx * scalingRatio;
                    if (scalingRatio <= 0)
                    {
                        break;
                    }
                }
                if (scalingRatio > 0)
                {
                    imageBorder.Height = heightPx;
                    imageBorder.Width = widthPx;
                }
            }
        }

        /// <summary>
        /// 判断执行渲染
        /// </summary>
        /// <param name="papersize"></param>
        /// <param name="landscape"></param>
        private void JudgmentExecution(PaperSize papersize, bool landscape)
        {
            if (papersize != null)
            {
                if (landscape)
                {
                    Reset(papersize.Width, papersize.Height);
                }
                else
                {
                    Reset(papersize.Height, papersize.Width);
                }
            }
        }

        /// <summary>
        /// 将bitmapImage对象转换成Bitmap对象
        /// </summary>
        /// <param name="bitmapImage"></param>
        /// <returns></returns>
        private static System.Drawing.Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
        {
            using System.IO.MemoryStream outStream = new System.IO.MemoryStream();
            BitmapEncoder enc = new BmpBitmapEncoder();
            enc.Frames.Add(BitmapFrame.Create(bitmapImage));
            enc.Save(outStream);
            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);

            return bitmap;

        }

        /// <summary>
        /// byte[]转为BitmapImage
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        public static BitmapImage ToImage(byte[] byteArray)
        {
            BitmapImage bmp = null;

            try
            {
                bmp = new BitmapImage();
                bmp.BeginInit();
                bmp.StreamSource = new MemoryStream(byteArray);
                bmp.EndInit();
            }
            catch
            {
                bmp = null;
            }

            return bmp;
        }

        /// <summary>
        /// 开始打印
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BeginPrint_Click(object sender, RoutedEventArgs e)
        {
            bool sr = int.TryParse(fromInput.Text, out int start);
            bool er = int.TryParse(toInput.Text, out int end);
            string[] pages = pageRangeInput.Text.Split("-");

            FrontEndUtils.WaitingOperation("打印图像", () =>
            {
                if (ImageFilePaths != null && ImageFilePaths.Count > 0)
                {
                    switch (PagesType)
                    {
                        case PagesType.All:
                            foreach (string path in ImageFilePaths)
                            {
                                System.Drawing.Image img1 = new Bitmap(path);
                                //打印图像
                                PrinterHelper.PrintImage(img1, Landscape, PaperSize, Watermark);
                                img1?.Dispose();
                            }
                            break;
                        case PagesType.CurrentPage:
                            System.Drawing.Image img2 = new Bitmap(ImageFilePaths[Current - 1]);
                            //打印图像
                            PrinterHelper.PrintImage(img2, Landscape, PaperSize, Watermark);
                            img2?.Dispose();
                            break;
                        case PagesType.PageRangeMultiFrame:
                            if (!sr || !er)
                            {
                                FrontEndUtils.PopupMessage($"请输入正确的格式");
                                return;
                            }
                            else
                            {
                                if (start <= 0 || end > ImageFilePaths.Count || end < start)
                                {
                                    FrontEndUtils.PopupMessage($"输入的页数范围有误");
                                    return;
                                }
                                for (int i = start - 1; i < end; i++)
                                {
                                    string path = ImageFilePaths[i];
                                    System.Drawing.Image img3 = new Bitmap(path);
                                    //打印图像
                                    PrinterHelper.PrintImage(img3, Landscape, PaperSize, Watermark);
                                    img3?.Dispose();
                                }
                            }

                            break;
                        case PagesType.PageRange:
                            
                            if (pages.Length != 2)
                            {
                                FrontEndUtils.PopupMessage($"请输入正确的格式");
                                return;
                            }

                            int start1, end1;

                            bool sr1 = int.TryParse(pages[0], out start1);
                            bool er1 = int.TryParse(pages[1], out end1);

                            if (!sr1 || !er1)
                            {
                                 FrontEndUtils.PopupMessage($"请输入正确的格式");
                            }
                            else
                            {
                                if (start1 <= 0 || end1 > ImageFilePaths.Count)
                                {
                                    FrontEndUtils.PopupMessage($"输入的页数范围有误");
                                    return;
                                }
                                for (int i = start1 - 1; i < end1; i++)
                                {
                                    string path = ImageFilePaths[i];
                                    System.Drawing.Image img4 = new Bitmap(path);
                                    //打印图像
                                    PrinterHelper.PrintImage(img4, Landscape, PaperSize, Watermark);
                                    img4?.Dispose();
                                }
                            }

                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    System.Drawing.Image img = BitmapImage2Bitmap((BitmapImage)ImageSource);
                    //打印图像
                    PrinterHelper.PrintImage(img, Landscape, PaperSize, Watermark);
                    img?.Dispose();
                }
                FrontEndUtils.PopupMessage($"打印成功");
                _ = System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    DialogResult = true;
                }));
            }, true);
        }

        /// <summary>
        /// 取消打印
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
        }

        /// <summary>
        /// 页面加载完成以后
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PrintImageWindow_Loaded(object sender, RoutedEventArgs e)
        {
            //Trace.WriteLine((double)new LengthConverter().ConvertFrom($"21cm"));
            System.Drawing.Printing.PrinterSettings.PaperSizeCollection paperSizes = PrinterHelper.GetPaperSizes();
            foreach (PaperSize item in paperSizes)
            {
                if (item.Kind == PaperKind.A4)
                {
                    PaperSize = item;
                }
            }
            paperSizeComboBox.SelectedValue = PaperKind.A4;
            Reset(PaperSize.Height, PaperSize.Width);

            fromInput.Text = "1";
            toInput.Text = "1";
            if (ImageFilePaths is null || (ImageFilePaths != null && ImageFilePaths.Count == 0))
            {
                from.Opacity = 0.5D;
                to.Opacity = 0.5D;
                prompt.Opacity = 0.5D;
                fromInput.IsEnabled = false;
                toInput.IsEnabled = false;
                pageRangeInput.IsEnabled = false;
            }
        }

        /// <summary>
        /// 加载BitmapImage
        /// </summary>
        /// <param name="imagePath"></param>
        /// <returns></returns>
        public static BitmapImage GetImage(string imagePath)
        {
            BitmapImage bitmap = new BitmapImage();
            if (File.Exists(imagePath))
            {
                bitmap.BeginInit();
                bitmap.CacheOption = BitmapCacheOption.OnLoad;
                using Stream ms = new MemoryStream(File.ReadAllBytes(imagePath));
                bitmap.StreamSource = ms;
                bitmap.EndInit();
                bitmap.Freeze();
                GC.Collect();
            }
            return bitmap;
        }

        public PrintImageWindow()
        {
            InitializeComponent();
            DataContext = this;
            Loaded += PrintImageWindow_Loaded;
            Closed += PrintImageWindow_Closed;
        }

        private void PrintImageWindow_Closed(object sender, EventArgs e)
        {
            if (DialogResult == false)
            {
                FrontEndUtils.PopupMessage("打印取消");
            }
            ImageSource?.Freeze();
            GC.Collect();
        }

        public PrintImageWindow(string imageFilePath, string watermark = null) : this()
        {
            Watermark = watermark;
            ImageSource = GetImage(imageFilePath);
        }

        public PrintImageWindow(BitmapImage imageSource, string watermark = null) : this()
        {
            Watermark = watermark;
            ImageSource = imageSource;
        }

        public PrintImageWindow(ImageSource imageSource, string watermark = null) : this()
        {
            Watermark = watermark;
            ImageSource = imageSource;
        }

        public PrintImageWindow(byte[] imageByte, string watermark = null) : this()
        {
            Watermark = watermark;
            ImageSource = ToImage(imageByte);
        }

        public PrintImageWindow(List<string> imageFilePaths, string watermark = null) : this()
        {
            Watermark = watermark;
            Total = imageFilePaths.Count;
            ImageFilePaths = imageFilePaths;
            ImageSource = GetImage(imageFilePaths[0]);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PageRangeInput_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            PagesType = PagesType.PageRange;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FromInput_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            PagesType = PagesType.PageRangeMultiFrame;
        }
    }
}
